/**
 *
 *	@file worker.c
 *
 *  Created on: Jan 24, 2010
 *      Author: Marco Luisi
 */

#include "worker.h"



char *dir_name;
char *i_pipe; //rinominare nel client
char *o_pipe;
char *cwdir;
char *username;
char *wdir;

char **filenames;

DIR *dir;//rinominare in userdir?

int dim;
int i;
int go;
int in;
int out;
int pid;

int files_num;
int matrices_num;
int dim_mat;
int temp;

struct dirent *file;

matrix_t *matrices;

volatile int cpid;// meglio int o char?
//volatile char *cpid;

//gestire sigpipe

int main(int argc, char **argv) {
	struct sigaction term_action;
	bzero(&term_action, sizeof(term_action));
	term_action.sa_handler = term_handler;
	sigaction(SIGTERM, &term_action, NULL);

	struct sigaction int_action; //ignora altrimenti sigint su nmat uccide tutto in foreground
	bzero(&int_action, sizeof(int_action));
	int_action.sa_handler = SIG_IGN;
	sigaction(SIGINT, &int_action, NULL);
	printf("Worker DEBUG: worker avviato\n");
	cpid = atoi(argv[2]);//ricontrollare se serve int
	username = strdup(argv[1]);
	printf("Worker DEBUG: worker per %s:%d\n", username,cpid);
	init();

	message_t m;

	//EC_NULL_E(matrices = malloc(n * sizeof(matrix_t)), "asd");
	go = 1;
	while(go){
		go = serve();
	}

	return 0;
}// fine main


/**
 * La funzioni init provvede ad aprire le pipe di comunicazione
 * con il client e alla apertura della directory per l'utente.
 *
 */
void init() {
	//char **filenames;
	printf("DEBUG WORKER: init()\n");
	//inizializzazione file di log
	//con data nome utente e pid
	//chiudere quello che è aperto nel server?

	//gestione pipe vs client
	EC_NULL_E(i_pipe = malloc(30 * sizeof(char)), "NMAT Worker errore"); // le dimensioni..
	sprintf(i_pipe, "%s%d", "../clientserver", cpid);//EC!
	printf("DEBUG WORKER i_pipe = !%s!\n", i_pipe);
	//temp?
	EC_M1_E(mkfifo(i_pipe,0666),"NMAT Worker errore mkfifo pipe");
	EC_M1_E(in = open(i_pipe, O_RDWR),"NMAT Worker errore pipe"); //controllare nonblock
	printf("DEBUG WORKER in=!%d!\n", in);
	//pipe in ingresso creata ed aperta


	EC_NULL_E(o_pipe = malloc(30 * sizeof(char)), "NMAT Worker errore"); // le dimensioni..
	sprintf(o_pipe, "%s%d", "../serverclient",cpid);
	EC_M1_E(out = open(o_pipe, O_WRONLY),"NMAT Worker errore pipe out");
	printf("DEBUG WORKER out=!%d!\n", out);
	//pipe pronte

	wdir = malloc(PATH_MAX * sizeof(char));
	//gestione directory
	printf("Worker DEBUG:getcwd=%s\n", wdir);//stablire dim massima username
	EC_NULL_E(dir_name = malloc(30 * sizeof(char)), "NMAT Worker errore");
	snprintf(dir_name, 30,"./%s",username);
	printf("Worker DEBUG: directory !%s!\n", dir_name);
	EC_NULL_E(dir = opendir(dir_name), "Worker: errore apertura dir");
	EC_M1_E(chdir(dir_name), "Worker: errore apertura dir");
	//dir utente aperta

	//implementare una scansione dei file?
	//scorre la dir per trovare i file contenuti
	dim = 5;
	files_num = 0;
	i = 0;
	//errore qui!!!

	EC_NULL_E(filenames = malloc(5 * sizeof(char*)) ,"NMAT WORKER errore memoria");
	printf("Worker debug scansione dir\n");
	while ((file = readdir(dir)) != NULL) { //controllo errore!
		printf("Worker debug dentro while scansione, nome file = !%s!\n",file->d_name);
		if (S_ISREG(file->d_type)) { //trovato file

			if (i == dim) { //controllo array
				dim *= 2;
				EC_NULL_E(filenames = realloc(filenames, dim * sizeof(char*)) ,"NMAT WORKER errore memoria");
			}
			printf("Worker debug trovato file\n");
			filenames[i] = strdup(file->d_name);
			printf("Worker debug trovato file %s\n",filenames[i]);
		}
	}//fine scansione dir
	printf("Worker debug fine scansione file\n");
	files_num = i + 1; //controllare gli indici
	EC_NULL_E(filenames = realloc(filenames, files_num * sizeof(char*)) ,"NMAT WORKER errore memoria");


	//log-> num files

	//inizializzazione array per le matrici
	dim_mat = 5;
	EC_NULL_E(matrices = malloc(dim_mat * sizeof(matrix_t)),"NMAT WORKER errore memoria");
	printf("DEBUG WORKER: fine init()\n");
}//fine init


int serve(){
	printf("Worker DEBUG: serve()\n");
	message_t cmd_msg;
	EC_M1(receive(in, &cmd_msg));//con un errore si esce dal ciclo,ma non si comunica al client..
	//msgprint(&cmd_msg);

	//ricevuto il messaggio, si esegue la richiesta
	switch(cmd_msg.cmdcode) {

	case(_load):{

	}


	}


	printf("Worker DEBUG: fine serve()\n");
	return 0;
}








//mantere la lista file anche nel client?
//int load(char* filename){
//	EC_M1_P(fd = open(filename,O_WRONLY),"NMAT Worker: errore i/o file");
//
//
//
//	EC_M1_P(close(fd),"NMAT Worker: errore i/o file");
//}

int fileToMat(){ //si passa l'array di struct, o direttamente la struct?



}


//int load(char *filename) { // versione con fopen
//	FILE * file;
//	EC_NULL_E(fopen(filename, "r"), "NMAT Client: errore apertura file.");//deve fare return -1
//
//
//}



//int load(char *filename) { //versione SC
//	int fd;
//	int dim;
//	char *buffer;
//	struct  stat statbuf;
//	EC_M1(fd = open(filename,O_RDONLY)); //rivedere l'ec
//	EC_M1(stat(filename, &statbuf));// ec?
//	if (!S_ISREG(statbuf.st_mode)) {
//		//errore
//		return -1;
//	}
//	dim = (int) statbuf.st_size;
//	EC_NULL(buffer = malloc(dim * sizeof(char)));
//	EC_M1(read(fd, buffer,dim));
//	printf("load ha letto:\n");
//	printf("%s",buffer);
//	printf("fine!\n");
//
//
//
//	close(fd);
//
//	//unlink
//}



//come chiedere se sovrascr
int save(char* filename){ //con un int per l'opzione di riscrittura?
	int i;
	int fd;
	EC_M1_P(fd =open(filename,O_WRONLY),"NMAT Worker: errore i/o file");
	//creazione file qui?

	for(i = 0; i<matrices_num; i++){
		//EC_M1(matToFile(matrices[i]));

	}

	EC_M1_P(close(fd),"NMAT Worker: errore i/o file");

	return 0;
}


//int matsToFile(){
//
//	//scrittura info mat
//	//nome
//	//dim
//	//ciclo scrittura righe
//
//}

/*! Funzione di controllo: stampa del messaggio ricevuto
 *
 */

//void msgprint(message_t *m) { //fare una print generica in un util.h o print.h !!!
//	int i;
//	printf("Worker: Debug MSGPRINT:\n");
//	if (&m != NULL) {
//		printf("cmdcode= %d || argnum= %d || nnum= %d\n", m->cmdcode, m->argnum,
//				m->nnum);
//		if (m->argnum) {
//			for (i = 0; i < m->argnum; i++) {
//				printf("arg[%d]=%s\n", i, m->args[i]);
//			}
//		}
//		if (m->nnum) {
//			for (i = 0; i < m->nnum; i++) {
//				printf("num[%d]=%g\n", i, m->numbers[i]);
//			}
//		}
//
//	}
//
//}//fine msgprint



//temporaneamente presa da nmcom
int receive(int ch, message_t *msg) { // meglio passare il riferimento a message?

	int rd;
	int len;
	int i;
	int tmp;
	//setup iniziale del messaggio
	EC_M1(read(ch, &(msg->cmdcode), sizeof(int)));
	EC_M1(read(ch, &(msg->argnum), sizeof(int)));
	EC_M1(read(ch, &(msg->nnum), sizeof(int)));

	//lettura eventuali argomenti
	if (msg->argnum) {
		EC_NULL(msg->args = malloc(msg->argnum * sizeof(char*)));
		//salvarsi i limiti per evitare ogni volta di fare 2 accessi?

		for(i = 0; i < msg->argnum; i++) {
			EC_M1(read(ch,&len,sizeof(int))); //leggo la lunghezza della stringa da leggere
			EC_NULL(msg->args[i] = malloc(len * sizeof(char *))); //char o char*?
			EC_M1(read(ch, msg->args[i], len)); // lettura stringa
		}

	}

	//lettura eventuali numeri
	if (msg->nnum) {
		EC_NULL(msg->numbers = malloc(msg->nnum * sizeof(double)));
		for(i = 0; i < msg->nnum; i++){
			EC_M1(read(ch, &(msg->numbers[i]), sizeof(double)));
		}

		return msg->cmdcode;
	}


}










void term_handler(int signum) {
	printf("WORKER DEBUG TERMHANDLER\n");
	kill((pid_t) cpid, SIGTERM);//invio sigterm al client
	close(in);
	unlink(i_pipe);//controllare
	perror("unlink i_pipe");
	printf("WORKER DEBUG  exit da termhandler\n");
	exit(0);
}








